package gnss

import (
	"dgo/goutils/dnet"
	"net"
	"runtime"
	"sync/atomic"
)

type NtripSimpleCaster struct {
	connobj_cnt   int32
	listener      *dnet.NetListener
	max_head_size uint16

	HandleNtripCltAcceptFunc func(conn *NtripSimpleCasterConn)

	/**
	  buf 是同一块, 如果需要异步处理需要进行复制
	*/
	HandleNtripCltRecvFunc   func(conn *NtripSimpleCasterConn, buf []byte)
	HandleNtripCltCloseFunc  func(conn *NtripSimpleCasterConn)
	HandleNtripSvrAcceptFunc func(conn *NtripSimpleCasterConn)

	/**
	  buf 是同一块, 如果需要异步处理需要进行复制
	*/
	HandleNtripSvrRecvFunc  func(conn *NtripSimpleCasterConn, buf []byte)
	HandleNtripSvrCloseFunc func(conn *NtripSimpleCasterConn)

	OnListenSucc func(network, addr string)
}

func NewNtripSimpleCaster() *NtripSimpleCaster {
	rval := &NtripSimpleCaster{listener: dnet.NewNetListener()}
	rval.max_head_size = 512
	rval.listener.HandleConnFunc = rval.HandleConn
	rval.listener.OnListenSucc = func(network, addr string) {
		if rval.OnListenSucc != nil {
			rval.OnListenSucc(network, addr)
		}
	}
	return rval
}

func (this *NtripSimpleCaster) GetConnObjCnt() int32 {
	return this.connobj_cnt
}

func (this *NtripSimpleCaster) ConfigAddr(network, addr string) {
	this.listener.Config(network, addr)
}

func (this *NtripSimpleCaster) handleNtripCltAccept(conn *NtripSimpleCasterConn) {
	fn := this.HandleNtripCltAcceptFunc
	if fn != nil {
		fn(conn)
	}
}

func (this *NtripSimpleCaster) handleNtripCltRecvBuf(conn *NtripSimpleCasterConn, buf []byte) {
	fn := this.HandleNtripCltRecvFunc
	if fn != nil {
		fn(conn, buf)
	}
}

func (this *NtripSimpleCaster) handleNtripCltClose(conn *NtripSimpleCasterConn) {
	fn := this.HandleNtripCltCloseFunc
	if fn != nil {
		fn(conn)
	}
}

func (this *NtripSimpleCaster) handleNtripSvrAccept(conn *NtripSimpleCasterConn) {
	fn := this.HandleNtripSvrAcceptFunc
	if fn != nil {
		fn(conn)
	}
}

func (this *NtripSimpleCaster) handleNtripSvrClose(conn *NtripSimpleCasterConn) {
	fn := this.HandleNtripSvrCloseFunc
	if fn != nil {
		fn(conn)
	}
}

func (this *NtripSimpleCaster) handleNtripSvrRecvBuf(conn *NtripSimpleCasterConn, buf []byte) {
	fn := this.HandleNtripSvrRecvFunc
	if fn != nil {
		fn(conn, buf)
	}
}

func (this *NtripSimpleCaster) conn_finalize(obj *NtripSimpleCasterConn) {
	atomic.AddInt32(&this.connobj_cnt, -1)
}

func (this *NtripSimpleCaster) HandleConn(conn net.Conn) {
	ctx := newSimpleCasterConn(conn, this)
	atomic.AddInt32(&this.connobj_cnt, 1)
	runtime.SetFinalizer(ctx, this.conn_finalize)
	go ctx.HandleRecv()
}

func (this *NtripSimpleCaster) Open() {
	this.listener.CheckStart()
}

func (this *NtripSimpleCaster) CheckOpen() {
	this.listener.CheckStart()
}

func (this *NtripSimpleCaster) Close() {
	this.listener.Close()
}
